package com.atguigu.cloud.controller;

import cn.hutool.json.JSONObjectIter;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.atguigu.cloud.dto.DocumentDto;
import com.atguigu.cloud.feign.DocumentFeign;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 用戶表
 */
@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    private DocumentFeign documentFeign;

    //基于计数测试
    @RequestMapping("/getDocumentList/{id}")
    @CircuitBreaker(name = "poi-service", fallbackMethod = "getDocumentListFallback")
    public List<DocumentDto> getDocumentList(@PathVariable(value = "id") int id) {
        System.out.println("i = " + 1 / id);
        return documentFeign.getDocumentList();
    }

    //基于时间测试
    @RequestMapping("/getDocumentList2/{id}")
    @CircuitBreaker(name = "poi-service", fallbackMethod = "getDocumentListFallback")
    public List<DocumentDto> getDocumentList2(@PathVariable(value = "id") int id) {
        if (id == 0) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return documentFeign.getDocumentList();
    }

//    //=========Resilience bulkhead 的例子
    @RequestMapping("/getDocumentList3/{id}")
    @Bulkhead(name = "poi-service",fallbackMethod = "getDocumentListFallback",type = Bulkhead.Type.SEMAPHORE)
    public List<DocumentDto> getDocumentList3(@PathVariable("id") Integer id)
    {
        if (id==0){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return documentFeign.getDocumentList();
    }

    @RequestMapping("/getDocumentList4/{id}")
    @Bulkhead(name = "poi-service",fallbackMethod = "getDocumentListFallback",type = Bulkhead.Type.THREADPOOL)
    public List<DocumentDto> getDocumentList4(@PathVariable("id") Integer id)
    {
        if (id==0){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return documentFeign.getDocumentList();
    }

    @RequestMapping("/getDocumentList5/{id}")
    @Bulkhead(name = "poi-service",fallbackMethod = "getDocumentListSyncFallback",type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture getDocumentList5(@PathVariable("id") Integer id)
    {
        if (id==0){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return CompletableFuture.supplyAsync(()->documentFeign.getDocumentList());
    }




    //兜底方法
    public CompletableFuture getDocumentListSyncFallback(Integer i, Throwable throwable) {

        return  CompletableFuture.supplyAsync(()-> {
            ArrayList<DocumentDto> objects = new ArrayList<>();
            DocumentDto documentDto = new DocumentDto();
            documentDto.setDescription("失败了");
            objects.add(documentDto);
            return objects;
        });
    }

    //兜底方法
    public List<DocumentDto> getDocumentListFallback(Integer i, Throwable throwable) {
        ArrayList<DocumentDto> objects = new ArrayList<>();
        DocumentDto documentDto = new DocumentDto();
        documentDto.setDescription("失败了");
        objects.add(documentDto);
        return  objects;
    }


    //限流测试
    @RequestMapping("/currentLimiting/{id}")
    @RateLimiter(name = "poi-service",fallbackMethod = "currentLimitingFallback")
    public String currentLimiting(@PathVariable("id") Integer id)
    {
        return JSONUtil.toJsonStr(documentFeign.getDocumentList());
    }
    public String currentLimitingFallback(Integer id,Throwable t)
    {
        return "你被限流了，禁止访问/(ㄒoㄒ)/~~";
    }
}
